#!/usr/bin/python
# -*- coding: utf-8 -*-

import itertools
import math

from pyglet.gl import *
from pyglet.graphics import *

# user definited-modules
import color as cr
import utils


class Shape:
	"""Ancerstor of all the classes in this module.
	
	Represent a undefinited shape that can be drawed, translated and rotated
	"""
	def draw(self):
		"""Draw the shape using pyglet's vertex_list"""
		self.vertex_list.draw(self.mode)
	
	def translate(self, x=0, y=0):
		for n, vertex in enumerate(self.vertex_list.vertices):
			if n % 2:
				self.vertex_list.vertices[n] += y
			else:
				self.vertex_list.vertices[n] += x
		
		if hasattr(self, 'collision_init'):
			self.collision_init()

class Point(Shape):
	def __init__(self, (x, y), color=(255, 255, 255, 255)):
		self.mode = GL_POINTS
		self.vertex_list = vertex_list(1,
			('v2i', (x, y)),
			('c4B', cr.check(color))
		)

class Line(Shape):
	def __init__(self, vertices, color=(255, 255, 255, 255)):
		self.mode = GL_LINES
		self.vertex_list = vertex_list(2,
			('v2i', tuple(itertools.chain(*vertices))),
			('c4B', cr.check(color)*2)
		)

class Triangle(Shape):
	def __init__(self, vertices, color=(255, 255, 255, 255), strip=False):
		self.mode = strip and GL_LINE_LOOP or GL_TRIANGLES
		self.vertex_list = vertex_list(3,
			('v2i', tuple(itertools.chain(*vertices))),
			('c4B', cr.check(color)*3)
		)
		
		self.collision_init()
	
	def collision_init(self):
		vs = self.vertex_list.vertices
		vx = map(float, vs[::2])
		vy = map(float, vs[1::2])
		vertices = zip(vx, vy)
		self.rect = (min(vx), min(vy), max(vx), max(vy))
		
		self.lati = []
		for v1, v2 in itertools.combinations(vertices, 2):
			if v2[0] - v1[0] != 0:
				m = (v2[1] - v1[1]) / (v2[0] - v1[0])
				q = v1[1] - m*v1[0]
				self.lati.append((m, q))
	
	def contains(self, x, y):
		if self.rect[0] <= x <= self.rect[2]:
			if self.rect[1] <= y <= self.rect[3]:
				intersections = 0
				
				for lato in self.lati:
					m, q = lato
					if m*x + q < y:
						intersections += 1
				
				if intersections % 2:
					return True
		
		return False

class Rectangle(Shape):
	def __init__(self, (x, y, width, height), color=(255, 255, 255, 255),
			strip=False):
		
		self.mode = strip and GL_LINE_LOOP or GL_QUADS
		self.vertex_list = vertex_list(4,
			('v2i', (x, y, x+width, y, x+width, y+height, x, y+height)),
			('c4B', cr.check(color)*4)
		)
	
	def contains(self, x, y):
		vs = self.vertex_list.vertices
		if vs[0] < x < vs[4]:
			if vs[1] < y < vs[5]:
				return True
		
		return False

class Polygon(Shape):
	def __init__(self, vertices, color=(255, 255, 255, 255), strip=False):
		self.mode = strip and GL_LINE_LOOP or GL_POLYGON
		
		pn = len(vertices)
		self.vertex_list = vertex_list(pn,
			('v2i', tuple(itertools.chain(*vertices))),
			('c4B', cr.check(color)*pn)
		)
		
		self.collision_init()
	
	def collision_init(self):
		vs = self.vertex_list.vertices
		vx = map(float, vs[::2])
		vy = map(float, vs[1::2])
		vertices = zip(vx, vy)
		vertices.append((vs[0], vs[1]))
		self.rect = (min(vx), min(vy), max(vx), max(vy))
		
		self.lati = []
		for id, v1 in enumerate(vertices[:-1]):
			v2 = vertices[id+1]
			if v2[0] - v1[0] != 0:
				m = (v2[1] - v1[1]) / (v2[0] - v1[0])
				q = v1[1] - m*v1[0]
				xs = (v1[0], v2[0])
				self.lati.append((min(xs), max(xs), m, q))
	
	def contains(self, x, y):
		if self.rect[0] <= x <= self.rect[2]:
			if self.rect[1] <= y <= self.rect[3]:
				intersections = 0
				
				for lato in self.lati:
					x1, x2, m, q = lato
					if x1 <= x < x2:
						print lato, x
						if m*x + q < y:
							intersections += 1
				print 
				if intersections % 2:
					return True
		
		return False

class Circle(Shape):
	def __init__(self, (x, y), radius, color=(255, 255, 255, 255), strip=False):
		self.mode = strip and GL_LINE_LOOP or GL_TRIANGLE_FAN
		self.radius = radius
		self.center = (x, y)
		
		if strip:
			vertices = []
		else:
			vertices = [float(x), float(y)]
		
		for deg in range(0, 361, 5):
			angle = (deg * math.pi) / 180
			vertices.extend((x + math.sin(angle)*radius, y + math.cos(angle)*radius))
		
		pn = len(vertices) / 2
		self.vertex_list = vertex_list(pn,
			('v2f', vertices),
			('c4B', cr.check(color)*pn)
		)
	
	def contains(self, x, y):
		d = math.sqrt((x-self.center[0])**2 + (y-self.center[1])**2)
		if d <= self.radius:
			return True
		
		return False